package wili.attrMapping._user.b1.exp;

import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.function.Predicate;
import java.util.stream.Collectors;

import wili.c.Ca;
import wili.c.File9a;
import wili.c.Str9a;
import wili.c.WillyConf;

/**
 * @author weila 2022年10月6日
 */
class AndOrExp2_test {
	static Map<String, Set<String>> varNameToValuesMap = new TreeMap<>();

	/**
	 * 搜集变量所有可能的取值。
	 */
	static void findOrPrint_varNameToValuesMap(AndOrExp2 andOrRoot) {
		if (andOrRoot == null) {// print.
			Ca.log("\n================valuesMap:" + varNameToValuesMap.size());
			for (String name : varNameToValuesMap.keySet()) {
				Set<String> set = varNameToValuesMap.get(name);
				String st = set.stream().collect(Collectors.joining(", ")).trim();
				if (st.equals("Y") || st.equals("N")) {
					st = "Y, N";
				}
				Ca.log(name + "\t=" + st);
			}
			return;
		}
		List<MathExpB1> mathExps = new ArrayList<>();
		andOrRoot.rootNode.findMathExp_all("", mathExps);
		for (MathExpB1 exp : mathExps) {
			exp.traverse(new Predicate<MathExpB1>() {
				void append(MathExpB1 va, MathExpB1 value, Map<String, Set<String>> valuesMap) {
					if (va instanceof Varb1) {
						Varb1 var = va.toVar();
						if (value instanceof Valueb1) {
							Valueb1 value2 = (Valueb1) value.toValue();
							Set<String> set = valuesMap.get(var.name);
							if (set == null) {
								valuesMap.put(var.name, set = new TreeSet<>());
							}
							set.add(value2.strValue);
						}
					}
				}

				@Override
				public boolean test(MathExpB1 exp) {
					if (exp instanceof Cpb1) {
						Cpb1 cp = exp.toCpExp();
						if (cp.ll instanceof Varb1) {
							append(cp.ll, cp.rr, varNameToValuesMap);
						}
					} else if (exp instanceof Funb1) {
						Funb1 fun = (Funb1) exp;
						if (fun.name.equals("includes")) {
							if (fun.arg instanceof Varb1) {
								for (MathExpB1 ele : fun.args) {
									if (ele instanceof Valueb1) {
										append(fun.arg, ele, varNameToValuesMap);
									}
								}
							}
						}
					}
					return false;
				}
			});
		}
	}

	public static void match_all_file_test(int use) {
		if (use < 0)
			return;
		List<File> files = new ArrayList<>();
		String f1 = WillyConf.AppDir + "src/main/java/wili/b1/client/a1";
		String f2 = WillyConf.AppDir + "src/main/java/wili/b1/client/a2";
		String f3 = WillyConf.AppDir + ":/sapB1/resources/detailView";
		// String f4 = "D:/sapB1/resources/listView";
		String[] paths = { f1, f2, f3 };
		for (String path : paths) {
			files.addAll(Arrays.asList(new File(path).listFiles(e -> e.getName().endsWith(".json"))));
		}
		//
		int ind = 0;
		Set<String> varNames = new TreeSet<>();
		for (int i = 0; i < files.size(); i++) {
			File file = files.get(i);
			if (file.getName().equals("PurchaseDOC1_Service.detailView.json"))
				continue;
			Ca.log("======================file:" + file.getName());
			String fileSt = File9a.strOfFile(file, "");
			String fmReg = "`(formula|editable|formulaUpdateMode|formulaViewMode|editableFormular|visibleFormular|editableFormular)`:\\s*`([^`]+)`"
					.replace("`", "\"");
			List<String> fmSet = Str9a.findAllRegMatch_(fmReg, 2, fileSt, 0);
			{
				for (String fm : fmSet) {
					++ind;
					Ca.log("\n" + ind + ">>>fm: " + fm);
					if (fm.contains("\"") || fm.endsWith("\\")) {
						Ca.log("WARN: can not parse formula contains '\"'");
						continue;
					}
					if (ind == 122)
						Ca.pause();
					AndOrExp2 aa = AndOrExp2.newInst(-1, fm);
					aa.print(-1);
					{
						List<Varb1> vars = new ArrayList<>();
						aa.rootNode.findVarList("", vars);
						Ca.log("varNames: " + vars.size()
								+ vars.stream().map(e -> e.name).collect(Collectors.toSet()).toString());
					}
					findOrPrint_varNameToValuesMap(aa);
					// varNames.addAll(mathExps.stream().map(e -> e.name).toList());
				}
			}
		}
		Ca.log(-1, varNames.stream().map(e -> "\n" + e + "\t=x,y").collect(Collectors.toList()));
		findOrPrint_varNameToValuesMap(null);
	}

	static void match_test(int use) {
		if (use < 0)
			return;
		String st = "${aa} !== 'C' && (${view>/$EditMode/editMode} eq true|| [undefined, null,'-1'].includes(${DocEntry}))";
		st = "{=${view>/$EditMode/editMode} && (${VChangeRdr} !== 'N' && ${ObjType} !== '13' && ${ObjType} !== '14' && ${VDeliveryStatus} !== 'N' || [undefined, null].includes(${DocEntry}))}";
		st = "!${view>/$EditMode/viewMode} && ((${DocStatus} !== 'C' || ${ObjType}  === '234000031'))";
		st = "({VLawsSet} eq 'CL' or {VLawsSet} eq 'TR')and ({ObjType} eq '59' or {ObjType} eq '60')";
		st = "{= #DEFALUT_EDITABLE#}";
		st = "{=#DEFALUT_EDITABLE456# && ({/DocEntry} eq null)}";
		st = "!${view>/$EditMode/viewMode} && (${/DocEntry} === null || ${ObjType} !== '13' && ${ObjType} !== '15' && ${ObjType} !== '234000031' || ${VDocStatus} !== 'C' && ${VDocStatus} !== 'A' && ${VDeliveryStatus} !== 'N')";
		st = "#DEFALUT_EDITABLE# && (({VChangeRdr} !== 'N' || {DocEntry} === null))";
		st = "{=#DEFALUT_EDITABLE# && ({=(${VChangeRdr} !== 'N'  || ([undefined,null].includes(${DocEntry}) || ${ObjType} === '234000031' && ${VDocStatus} !== 'C' && ${VDocStatus} !== 'A'))})}";
		st = "!!${DocEntry}";
		st = "false eq ({VDocStatus} eq 'C' and ({ObjType} eq 1470000113 or {ObjType} eq 540000006 or {ObjType} eq 22))";
		//st = "{a}+{c} eq {b}";
		AndOrExp2 aa = AndOrExp2.newInst(-1, st);
		aa.print(1);
		List<Varb1> vars = new ArrayList<>();
		aa.rootNode.findVarList("", vars);
		Ca.log("varNames: " + vars.size() + vars.stream().map(e -> e.name).collect(Collectors.toList()).toString());
	}

	public static void test(int use) {
		if (use < 0)
			return;
		match_test(1);
		if ("".isEmpty())
			return;
		match_test(1);
		match_all_file_test(1);
	}

	public static void main(String[] args) {
		test(1);
	}
}